<?php

namespace Ruben\Aliyun;
use Think\Log;
use vod\Request\V20170321\DeleteVideoRequest;
use Cdn\Request\V20141111\DescribeLiveStreamOnlineUserNumRequest;
use Cdn\Request\V20141111\ForbidLiveStreamRequest;
use Cdn\Request\V20141111\ResumeLiveStreamRequest;
use Cdn\Request\V20141111\DescribeLiveStreamSnapshotInfoRequest;

class Live
{
    private $vhost;
    private $side_vhost;
    private $appName;
    private $privateKey;
    private $side_privateKey;
    private $accessKey;
    private $accessSecret;

    public function __construct($config)
    {
        $this->vhost = $config['host'];
        $this->side_vhost = $config['side_host'];
        $this->appName = $config['app_name'];
        $this->accessKey = $config['access_key'];
        $this->accessSecret = $config['access_secret'];
        $this->privateKey = $config['private_key'];
        $this->side_privateKey = $config['side_private_key'];
    }

    /**
     * 生成鉴权key
     *
     * @param string $streamName 流名称，一般与业务相关
     * @param int $expired 有效时长(秒)
     * @return string
     */
    private function genAuthKey($streamName, $expired)
    {
        $time = time() + $expired;
        $rand = 0;
        $uid = 0;
        $sstring = "/{$this->appName}/{$streamName}-{$time}-{$rand}-{$uid}-{$this->privateKey}";
        $key = "{$time}-{$rand}-{$uid}-" . md5($sstring);
        return $key;
    }

    //边缘推流
    private function genAuthKey2($streamName, $expired)
    {
        $time = time() + $expired;
        $rand = 0;
        $uid = 0;
        $sstring = "/{$this->appName}/{$streamName}-{$time}-{$rand}-{$uid}-{$this->side_privateKey}";
        $key = "{$time}-{$rand}-{$uid}-" . md5($sstring);
        return $key;
    }

    /**
     * 获取直播推/拉地址
     *
     * @param string $streamName 流名称，一般与业务相关
     * @param int $expired 推流地址有效时长（秒）
     * @return array push为推流地址 pull为拉流地址，包含 rtmp flv m3u8
     */
    public function getLiveUrls($streamName, $auth = true, $expired = 3000)
    {
        $rst = [];
//        $rst['push'] = $this->getPublishUrl($streamName, $auth, $expired);//中心推流
        $rst['push'] = $this->getPublishUrl2($streamName, $auth, $expired);//边缘推流
        $rst['pull'] = $this->getPullUrls2($streamName, $auth, $expired, ['lud', 'lhd', 'lsd', 'lld', 'original']);
        return $rst;
    }

    /*
     * 获取中心推流
     */
    private function getPublishUrl($streamName, $auth, $expired)
    {
        $url = "rtmp://video-center-sg.alivecdn.com/{$this->appName}/{$streamName}";//中心推流地址
        $params = [];
        $params['vhost'] = $this->vhost;
        
        if ($auth === true){
            $params['auth_key'] = $this->genAuthKey($streamName, $expired);
        };
        $url = $url . '?' . http_build_query($params);
        Log::record($url,'getPublishUrl',true);
        return  $url;
    }

    /*
     * 获取边缘推流地址
     */
     private function getPublishUrl2($streamName, $auth, $expired)
    {
        $url = "rtmp://{$this->side_vhost}/{$this->appName}/{$streamName}";//边缘推流地址
        $params = [];
        if ($auth === true) {$params['auth_key'] = $this->genAuthKey2($streamName, $expired);};
        $url = $url . '?' . http_build_query($params);
        Log::record($url,'getPublishUrl',true);
        return  $url;
    }

    /**
     * 生成多个清晰度的拉流地址。
     * 直播播放地址由不同参数拼接而成，由 播放域名 + AppName + StreamName + “_“ + 转码模板名称
     *
     * @param string $streamName 流名称
     * @param boolean $auth 是否需要鉴权
     * @param integer $expired 过期时间
     * @param array $clarities 清晰度
     * @return array
     */
    private function getPullUrls($streamName, $auth, $expired, $clarities = ['original'])
    {
        $pullUrls = [];
        foreach ($clarities as $clarity) {
            $urls = $this->getPullUrl($streamName, $auth, $expired, $clarity);
            $pullUrls = array_merge($pullUrls, $urls);
        }
        return $pullUrls;
    }

     private function getPullUrls2($streamName, $auth, $expired, $clarities = ['original'])
    {
        $pullUrls = [];
        foreach ($clarities as $clarity) {
            $urls = $this->getPullUrl2($streamName, $auth, $expired, $clarity);
            $pullUrls = array_merge($pullUrls, $urls);
        }
        return $pullUrls;
    }


    /**
     * 直播播放地址由不同参数拼接而成，由 播放域名 + AppName + StreamName + “_“ + 转码模板名称
     *
     * @param string $streamName 流名称
     * @param boolean $auth 是否需要鉴权
     * @param integer $expired 过期时间
     * @param string $clarity 清晰度 lud-超清 lhd-高清 lsd-标清 lld-流畅 original-原画
     * @return array
     */
    private function getPullUrl($streamName, $auth, $expired, $clarity = 'original')
    {
        $suffix = $clarity === 'original' ? '' : "_{$clarity}";
        $streamName .= $suffix;
        $rtmpStreamName = $streamName;
        $flvStreamName = $streamName . '.flv';
        $m3u8StreamName = $streamName . '.m3u8';
        if ($auth === true) {
            $rtmp = "rtmp://{$this->vhost}/{$this->appName}/{$streamName}?auth_key=" . $this->genAuthKey($rtmpStreamName, $expired);
            $flv =  "http://{$this->vhost}/{$this->appName}/{$streamName}.flv?auth_key=" . $this->genAuthKey($flvStreamName, $expired);
            $m3u8 = "http://{$this->vhost}/{$this->appName}/{$streamName}.m3u8?auth_key=" . $this->genAuthKey($m3u8StreamName, $expired);
        } else {
            $rtmp = "rtmp://{$this->vhost}/{$this->appName}/{$streamName}";
            $flv =  "http://{$this->vhost}/{$this->appName}/{$streamName}.flv";
            $m3u8 = "http://{$this->vhost}/{$this->appName}/{$streamName}.m3u8";
        }
        $urls = [];
        $urls["rtmp{$suffix}"] = $rtmp;
        $urls["flv{$suffix}"] = $flv;
        $urls["m3u8{$suffix}"] = $m3u8;
        return $urls;
        // return compact('rtmp', 'flv', 'm3u8');
    }

    
     private function getPullUrl2($streamName, $auth, $expired, $clarity = 'original')
    {
        $suffix = $clarity === 'original' ? '' : "_{$clarity}";
        $streamName .= $suffix;
        $rtmpStreamName = $streamName;
        $flvStreamName = $streamName . '.flv';
        $m3u8StreamName = $streamName . '.m3u8';
        if ($auth === true) {
            $rtmp = "rtmp://{$this->vhost}/{$this->appName}/{$streamName}?auth_key=" . $this->genAuthKey($rtmpStreamName, $expired);
            $flv =  "http://{$this->vhost}/{$this->appName}/{$streamName}.flv?auth_key=" . $this->genAuthKey($flvStreamName, $expired);
            $m3u8 = "http://{$this->vhost}/{$this->appName}/{$streamName}.m3u8?auth_key=" . $this->genAuthKey($m3u8StreamName, $expired);
        } else {
            $rtmp = "rtmp://{$this->vhost}/{$this->appName}/{$streamName}";
            $flv =  "http://{$this->vhost}/{$this->appName}/{$streamName}.flv";
            $m3u8 = "http://{$this->vhost}/{$this->appName}/{$streamName}.m3u8";
        }
        $urls = [];
        $urls["rtmp{$suffix}"] = $rtmp;
        $urls["flv{$suffix}"] = $flv;
        $urls["m3u8{$suffix}"] = $m3u8;
        return $urls;
        // return compact('rtmp', 'flv', 'm3u8');
    }

    /**
     * 禁止某条流的推送，可以预设某个时刻将流恢复
     *
     * @param string $stream 流名称
     * @param string $streamType 用于指定主播推流还是客户端拉流，目前支持 “publisher”(主播推送)
     * @param string $resumeTime 恢复流的时间 UTC 时间 格式：2015-12-01T17:37:00Z
     * 
     * @return void
     */
    public function forbidLiveStream($stream, $resumeTime = null, $streamType = 'publisher')
    {
        require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-cdn');
        $iClientProfile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($iClientProfile);
        $request = new ForbidLiveStreamRequest();
        $request->setLiveStreamType($streamType);
        $request->setAppName($this->appName);
        $request->setStreamName($stream);
        $request->setDomainName($this->vhost);
        try {
            $response = $client->getAcsResponse($request);
            return true;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * 恢复某条流的推送
     *
     * @param string $stream 流名称
     * @param string $streamType 用于指定主播推流还是客户端拉流，目前支持 “publisher”(主播推送)
     * 
     * @return void
     */
    public function resumeLiveStream($stream,$streamType = 'publisher')
    {
        require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-cdn');
        $iClientProfile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($iClientProfile);
        $request = new ResumeLiveStreamRequest();
        $request->setLiveStreamType($streamType);
        $request->setAppName($this->appName);
        $request->setStreamName($stream);
        $request->setDomainName($this->vhost);
        try {
            $response = $client->getAcsResponse($request);
            return true;
        } catch (\Exception $e) {
            throw $e;
        }
    }


    public function getDescribeLiveStreamSnapshotInfo($stream, $start, $end)
    {
         require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-cdn');
        $iClientProfile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($iClientProfile);
        $request = new DescribeLiveStreamSnapshotInfoRequest();
        $request->setAppName($this->appName);
        $request->setStreamName($stream);
        $request->setDomainName($this->vhost);
        $request->setStartTime(date('Y-m-d\TH:i:s\Z', $start));
        $request->setEndTime(date('Y-m-d\TH:i:s\Z', $end));
        try {
            $response = $client->getAcsResponse($request);
            dump($response);
        } catch (\Exception $e) {
            throw $e;
        }
    }




    /**
     * 获取实时在线人数
     *
     * @return array [[push_url] => [nums]]
     */
    public function getOnlineNums()
    {
        require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-vod');
        $iClientProfile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($iClientProfile);
        $request = new DescribeLiveStreamOnlineUserNumRequest();
        $request->setDomainName($this->vhost);
        $request->setAppName($this->appName);
        // $request->setStreamName('15_060275_0624');
        $response = $client->getAcsResponse($request);

        $onlineInfo = [];
        foreach ($response->OnlineUserInfo->LiveStreamOnlineUserNumInfo as $info) {
            $onlineInfo[$info->StreamUrl] = $info->UserNumber;
        }
        return $onlineInfo;
    }

    /**
     * 获取播放鉴权码
     *
     * @param string $vid vod上的视频ID
     * @return void
     */
    public function getVodAuthKey($vid)
    {
        require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        // require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-vod/vod/Request/V20170321/GetVideoPlayAuthRequest');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-vod');
        $profile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($profile);
        $request = new \GetVideoPlayAuthRequest();
        $request->setVideoId($vid);
        try {
            $response = $client->getAcsResponse($request);
            return $response->PlayAuth;
        } catch (\Exception $e) {}
    }

    /**
     * 删除视频
     *
     * @param [type] $vid
     * @return void
     */
    public function delVideo($vid)
    {
        require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-vod');
        $profile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($profile);
        $request = new DeleteVideoRequest();
        $vid = is_array($vid) ? implode(',', $vid) : $vid;
        $request->setVideoIds($vid);
        try {
            $response = $client->getAcsResponse($request);
        } catch (\Exception $e) {}
    }

    public function createUploadVideo()
    {
        require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-vod');
        $profile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($profile);
        $request = new \vod\Request\V20170321\CreateUploadVideoRequest();
        $request->setTitle("视频标题");
        $request->setAcceptFormat('JSON');

        //视频源文件名称(必须包含扩展名)
        $request->setFileName("aaaa.mp4");
        //视频源文件字节数
        $request->setFileSize(0);
        $request->setDescription("视频描述");
        //自定义视频封面URL地址
        $request->setCoverURL("http://cover.sample.com/sample.jpg");
        //上传所在区域IP地址
        // $request->setIP("127.0.0.1");
        // $request->setTags("标签1,标签2");
        //视频分类ID
        // $request->setCateId(0);
        $response = $client->getAcsResponse($request);
        return json_decode(json_encode($response), true);
        // dump($response);

    }

    public function getVideoInfo($vid)
    {
        require_once('aliyun-openapi-php-sdk/aliyun-php-sdk-core/Config.php');
        \Autoloader::addAutoloadPath('aliyun-php-sdk-vod');
        $profile = \DefaultProfile::getProfile('cn-shanghai', $this->accessKey, $this->accessSecret);
        $client = new \DefaultAcsClient($profile);
        $request = new \vod\Request\V20170321\GetPlayInfoRequest();
        $request->setVideoId($vid);
        try {
            $response = $client->getAcsResponse($request);
            return array_map(function($info) {
                return json_decode(json_encode($info), true);
            }, $response->PlayInfoList->PlayInfo);
        } catch (\Exception $e) {

        }

    }

    public function setAppName($appName)
    {
        $this->appName = $appName;
    }

    public function setPrivateKey($privateKey)
    {
        $this->privateKey = $privateKey;
    }

    public function setVhost($vhost)
    {
        $this->vhost = $vhost;
    }

    public function setAccessKey($accessKey)
    {
        $this->accessKey = $accessKey;
    }

    public function setAccessSecret($accessSecret)
    {
        $this->accessSecret = $accessSecret;
    }
}
